#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <iostream>
#include <cmath>
double fmin1(double, double);
double fmin2(double, double);

union LongDouble
{
    long p_num;
    double d_num;
};

int main(){
    long MAX = 10000;
    double c[MAX];
    double d[MAX];
    double d_0[MAX];
    double d_1[MAX];
    double d_2[MAX];
    srand(time(NULL));
    for (long i = 0; i < MAX; i++)
    {
        c[i] = (double)(rand())/RAND_MAX;
        d[i] = (double)(rand())/RAND_MAX;
    }
    auto start = std::chrono::high_resolution_clock::now();
    for (long i = 0; i < MAX; i++)
    {
        for(long j = i; j<MAX;j++){
            d_0[j] = fmin(c[j-i],d[j]);
        }
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::cout << "Execution time 0: " << duration.count() << " microseconds\n";

    start = std::chrono::high_resolution_clock::now();
    for (long i = 0; i < MAX; i++)
    {
        for(long j = i; j<MAX;j++){
            d_1[j] = fmin1(c[j-i],d[j]);
        }
    }
    end = std::chrono::high_resolution_clock::now();
    duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::cout << "Execution time 1: " << duration.count() << " microseconds\n";
    start = std::chrono::high_resolution_clock::now();
    for (long i = 0; i < MAX; i++)
    {
        for(long j = i; j<MAX; j++){
            d_2[j] = fmin2(c[j-i],d[j]);
        }
    }
    end = std::chrono::high_resolution_clock::now();
    duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::cout << "Execution time 2: " << duration.count() << " microseconds\n";
    for (long i = 0; i < MAX; i+=100)
    {
        printf("%ld\n",i);
        printf("%.20f\n",d_0[i]);
        printf("%.20f\n",d_1[i]);
        printf("%.20f\n",d_2[i]);
    }
    return 0;
}

double fmin1(double a, double b){
    if (a <= b)
    {
        return a;
    }
    return b;
}
double fmin2(double a, double b){
    long p;
    long pp = 0xffffffffffffffff;
    union LongDouble num1;
    num1.d_num = a;
    union LongDouble num2;
    num2.d_num = b;
    p = a<=b;
    pp = pp*p;
    union LongDouble num3;
    num3.p_num = (num1.p_num&pp)|(num2.p_num&(~pp));
    return num3.d_num;
}
